#!/usr/bin/python

from PIL import Image

from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen import canvas
from reportlab.lib.colors import black, white, gray, lightgrey,  darkgray,  red
from reportlab.lib.pagesizes import letter
from reportlab.lib.utils import ImageReader, LazyImageReader
from reportlab.platypus.tables import LINECAPS

import pprint

from hgbfe.layout.armor import drawArmor
from hgbfe.layout.info import drawMiscInfo
from hgbfe.layout.misc import drawZebraStripes,  drawActions,  drawCommand,  drawSkills,  drawState
from hgbfe.layout.traits import drawTraits,  drawTraitsBox,  drawTraitsBox2,  drawReferenceTraits
from hgbfe.layout.weapons import drawRangedWeapons,  drawThrownWeapons,  drawMeleeWeapons

from hgbfe.weapon import weaponCmp
from hgbfe.trait import traitCmp

cWidth = 252
cHeight  = 180
padding = 2
LINE_WIDTH = 0.1

stripeImage = "images/hazard_stripe.png"
factionImages = {
    "default": "images/icons/icon_hg.png",                 
    "north": "images/icons/icon_north.png",
    "south": "images/icons/icon_south.png",
    "paxton": "images/icons/icon_prdf.png",
    "pak": "images/icons/icon_pak.png",
    "cef" : "images/icons/icon_cef.jpg", 
    "caprice" : "images/icons/icon_caprice.jpg", 
    "talons" : "images/icons/icon_talons.jpg", 
}

pdfmetrics.registerFont(TTFont('LS-Bold', 'fonts/LiberationSans-Bold.ttf'))
pdfmetrics.registerFont(TTFont('LS', 'fonts/LiberationSans-Regular.ttf'))

def drawBorder(canvas, origin):
    canvas.setLineWidth(LINE_WIDTH)
    canvas.rect(origin[0], origin[1], cWidth, cHeight)
    canvas.rect(origin[0] + cWidth,  origin[1] ,  cWidth,  cHeight)
    
    # TODO: Add a dashed line for the 'bend here' idea?
    #canvas.line(origin[0] + cWidth,  origin[0] + cHeight,  origin[0] + cWidth,  origin[0])

def drawBackground(canvas, origin,  modelCount,  faction):
    stripe = ImageReader(stripeImage)
    
    canvas.drawImage(stripe, origin[0] + 0, origin[1] + 0, width=20, height=50)
    canvas.drawImage(stripe, origin[0] + 0, origin[1] + 49, width=20, height=50)
    canvas.drawImage(stripe, origin[0] + 0, origin[1] + 98, width=20, height=50)
    canvas.drawImage(stripe, origin[0] + 0, origin[1] + 147, width=20, height=33)
    
    #iconImage = ImageReader(factionImages['north'])
    iconImage = ImageReader(factionImages[faction])
    iconX = origin[0] + 2
    iconY = origin[1] + cHeight - 34
    #print "Drawing icon at coords (%i, %i)" % (iconX,  iconY)
    canvas.drawImage(iconImage, iconX, iconY, 
                    mask=(0,0,0,0,0,0), width=32, height=32)

    #print "Drawing HGB-FE watermark at coordinates (%i, %i)" % (watermarkX,  watermarkY)
    watermarkY = -1 * (origin[0] + 14) 
    watermarkX = origin[1] + 6   
    canvas.setFont("LS-Bold", 12)
    canvas.setFillColor(white)
    canvas.rotate(90)
    canvas.drawString(watermarkX,  watermarkY, "HGB-FE")
    canvas.rotate(-90)
    canvas.setFillColor(black)

def drawTitle(canvas, origin, model,  modelCount):    
    titleX = origin[0] + cWidth - 2
    titleY = origin[1] + cHeight - 9
    titleHeight = (origin[1] + cHeight) - 11
    
    canvas.setFont("LS-Bold", 9)    
    canvas.setFillColor(black)
    canvas.drawRightString(titleX,  titleY, model.name)
    
    canvas.setStrokeColor(black)
    lineX = origin[0] + cWidth - 140    
    canvas.line(lineX, titleHeight+1, (origin[0] + cWidth) - padding, titleHeight+1)
    
    subtitleY = titleY - 6
    #chassisX = lineX
    sizeX = (origin[0] + cWidth - lineX) / 3 + lineX
    #tvX = origin[0] + cWidth - 2
    tvX = lineX
    chassisX = origin[0] + cWidth - padding
    
    canvas.setFont("LS",  5)
    canvas.drawRightString(chassisX,  subtitleY,  "Type: %s" % model.chassis.title())
    #canvas.drawCentredString(sizeX,  subtitleY,  "Size: %i" % model.size)
    canvas.drawString(tvX,  subtitleY,  "TV: %i" % 0)

def drawMovement(canvas, origin, moveDict,  model,  modelCount):
    # Define our diminsions
    origin_x = origin[0]
    origin_y = origin[1]
    
    boxWidth = 80
    boxHeight = 17 + 6 + 6
    boxLeftX = (origin_x + cWidth) - (boxWidth + padding + 69)
    boxTopY = (origin_y + cHeight)  - 47
    boxBottomY = boxTopY - boxHeight
    
    titleHeight = 5
    headerHeight = 5
    zebraStripeHeight = 6    
    lineHeight = 5
    
    titleBottomY = boxBottomY + boxHeight - titleHeight
    headerBottomY = boxTopY - headerHeight
    zebraStartY = headerBottomY
    traitsLineY = zebraStartY - 12
    numStripes = 4
    lineStartY = headerBottomY - lineHeight - padding
    
    xCoordDict = {}
    startX = boxLeftX + 2  
    xCoordDict['type'] = startX    
    xCoordDict['mp'] = startX + 25
    xCoordDict['turn'] = startX + 42
    
    xCoordDict['st'] = startX + 46
    xCoordDict['cb'] = startX + 56
    xCoordDict['ts'] = startX + 66    

    # First, draw our zebra striping for the different movement modes
    drawZebraStripes(canvas,  boxLeftX,  boxWidth,  zebraStartY,  numStripes,  zebraStripeHeight)
    canvas.line(boxLeftX,  traitsLineY, boxLeftX + boxWidth, traitsLineY)
    
    # Draw title first
    titleHeight = 5
    canvas.setFillColor(black)
    canvas.setStrokeColor(black)
    canvas.rect(boxLeftX-5,  (boxTopY - boxHeight) ,  5,  boxHeight ,  stroke=1,  fill=1 )
    
    labelY = -1 * (origin[0] + 100)
    labelX = origin[1] +106
    canvas.setFillColor(white)        
    canvas.setFont("LS-Bold", 4)
    canvas.rotate(90)    
    canvas.drawString(labelX,  labelY, "MOVE")
    canvas.rotate(-90)
    
    # Now header
    headerHeight = 5
    headerY = boxTopY - headerHeight
    canvas.setFillColor(white)
    canvas.setStrokeColor(black)
    canvas.rect(boxLeftX, headerY, boxWidth, headerHeight, stroke=1, fill=0)
    canvas.setFillColor(black)
    canvas.setFont("LS", 4)
    headerY = headerY + 1
    canvas.drawString( xCoordDict['type'] , headerY , "TYPE")
    canvas.drawCentredString(xCoordDict['mp'] , headerY, "MP")
    canvas.drawString(xCoordDict['st'] , headerY, "STP")
    canvas.drawString(xCoordDict['cb'] , headerY, "CBT")
    canvas.drawString(xCoordDict['ts'] , headerY, "TOP")
    canvas.drawRightString(xCoordDict['turn'] , headerY, "TURN")
    
    # Now the datalines
    for idx in range(2):
        if idx in moveDict:            
            typeDict = moveDict[idx]
            typeY= lineStartY - (idx * (lineHeight + 1)) + padding
            drawMoveLine(canvas,  xCoordDict,  typeY,  padding,  typeDict)

    # Finally write the traits
    drawTraitsBox(canvas,  model.traits_move,  (origin[0] + 101,  origin[1] + 115),  boxWidth)

    # Finally, outline the entire box
    canvas.setStrokeColor(black)
    canvas.rect(boxLeftX, boxBottomY, boxWidth, boxHeight,  stroke=1)

def drawMoveLine(canvas,  xCoordDict,  yCoord,  padding,  typeDict):    
    canvas.setFillColor(black)
    canvas.setStrokeColor(black) 
    canvas.setFont("LS", 5)
    
    boxDims = 4
    lineY = yCoord
    
    canvas.drawString(xCoordDict['type'], lineY, typeDict["type"])
    movePointS = "%s" % (typeDict['movePoints'])
    canvas.drawCentredString(xCoordDict['mp'], lineY, movePointS)
    
    canvas.rect(xCoordDict['st'] + 2,  lineY,  boxDims,  boxDims)
    canvas.rect(xCoordDict['cb'] + 2,  lineY,  boxDims,  boxDims)
    canvas.rect(xCoordDict['ts'] + 2,  lineY,  boxDims,  boxDims)
    
    if typeDict["type"] is "Walker":
            canvas.drawRightString(xCoordDict['turn']  - 3, lineY, "0\"")
    elif typeDict["type"] is "Ground":
            canvas.drawRightString(xCoordDict['turn']  - 3, lineY, "2\"")
    elif typeDict["type"] is "Hover":
            canvas.drawRightString(xCoordDict['turn']  - 3, lineY, "4\"")
    elif typeDict["type"] is "Static":
            canvas.drawRightString(xCoordDict['turn']  - 3, lineY, "NA")
                
    
def drawEW(canvas, origin, ewDict,  model,  modelCount):    
    boxWidth = 80
    boxHeight = 31
    boxLeftX = (origin[0] + cWidth) - (boxWidth + padding + 69) 
    boxTopY = (origin[1] + cHeight) - 79
    boxBottomY = boxTopY - boxHeight
    boxTitleBottomY = boxBottomY + boxHeight - 4
    
    titleHeight = 5
    headerHeight = 5
    zebraStripeHeight = 6
    lineHeight = 5

    zebraStartY = boxTopY - 1
    traitsLineY = boxTopY - 19
    numStripes = 4

    # Line positions
    lineWidth = 3 + padding
    lineOneY = boxTopY - lineHeight - 1
    lineTwoY = lineOneY - lineHeight - 1
    lineThreeY = lineTwoY - lineHeight - 1

    labelOneX = boxLeftX + padding
    labelTwoX = labelOneX + (boxWidth/2) - padding
    valueOneX = labelTwoX - padding
    valueTwoX = boxLeftX + boxWidth - padding

    # First, draw our zebra striping for the different movement modes
    drawZebraStripes(canvas,  boxLeftX,  boxWidth,  zebraStartY,  numStripes,  zebraStripeHeight)
    canvas.setFillColor(black)
    canvas.line(boxLeftX,  traitsLineY, boxLeftX + boxWidth, traitsLineY)
    
    # Draw our title
    titleHeight = 5
    canvas.setFillColor(black)
    canvas.setStrokeColor(black)
    canvas.rect(boxLeftX-5,  (boxTopY - boxHeight) ,  5,  boxHeight ,  stroke=1,  fill=1 )
    
    labelY = -1 * (origin[0] + 100)
    labelX = origin[1] +72    
    canvas.setFillColor(white)        
    canvas.setFont("LS-Bold", 4)
    canvas.rotate(90)    
    canvas.drawString(labelX,  labelY, "EW")
    canvas.rotate(-90)

    # Draw the Labels
    canvas.setFont("LS", 5)    
    canvas.setFillColor(black)
    
    canvas.drawString(labelOneX, lineOneY, "Detect:")
    canvas.drawRightString(valueOneX, lineOneY, str(ewDict['detect']))
    
    canvas.drawString(labelTwoX, lineOneY, "Auto Comm:")
    canvas.drawRightString(valueTwoX, lineOneY, str(ewDict['autocomm'] * 2))
    
    canvas.drawString(labelOneX, lineTwoY, "Sensors:")
    sensorsS = "%+i" % ewDict['sensors']
    canvas.drawRightString(valueOneX, lineTwoY, sensorsS)
    
    canvas.drawString(labelTwoX, lineTwoY, "Comm:")
    commS= "%+i" % ewDict['comm'] 
    canvas.drawRightString(valueTwoX, lineTwoY, commS)
    
    if  not'ecm' in ewDict or ewDict['ecm'] == 0:
        canvas.setFillColor(lightgrey)
        canvas.drawRightString(valueOneX, lineThreeY, "NA")
    else:
        canvas.setFillColor(black)
        ecmS = "%+i" % ewDict['ecm']
        canvas.drawRightString(valueOneX, lineThreeY, ecmS)
    canvas.drawString(labelOneX, lineThreeY, "ECM:")
    
    if  not'eccm' in ewDict or ewDict['eccm'] == 0:
        canvas.setFillColor(lightgrey)
        canvas.drawRightString(valueTwoX, lineThreeY, "NA")
    else:
        canvas.setFillColor(black)
        eccmS = "%+i" % ewDict['eccm']
        canvas.drawRightString(valueTwoX, lineThreeY, eccmS)    
    canvas.drawString(labelTwoX, lineThreeY, "ECCM:")
    
    # Finally write the traits
    # Exclude any ECM or ECCM traits
    traitsL = []
    for trait in model.traits_ew:
        if not trait.name.lower().startswith("ecm") and not trait.name.startswith("eccm"):
            traitsL.append(trait)
    drawTraitsBox(canvas,  traitsL,   (origin[0] + 101,  origin[1] + 81),  boxWidth)
    
    # Finally draw the outline
    canvas.setStrokeColor(black)
    canvas.rect(boxLeftX, boxBottomY, boxWidth, boxHeight, stroke=1, fill=0) # outline
    

'''
    Draw a test output sheet
'''
def drawTest(modelsL,  faction):
    c = canvas.Canvas("hgbfe_test.pdf",  pagesize=letter)
    origin = (0, 0)
    modelCount = 0

    pp = pprint.PrettyPrinter(indent=4)
    startY = (letter[1] / 2) + (cHeight * 2)
    startX = (letter[0] / 2) - cWidth
       
    for model in modelsL:        
        #origin = (0,  modelCount * cHeight)
        origin = (startX,  (startY - (cHeight*(modelCount+1))))
        print "Drawing model named %s at coords (%i, %i)" % (model.name,  origin[0],  origin[1])
        
        drawBorder(c,  origin)        
        # Broken in PIL 1.1.7-1
        drawBackground(c, origin,  modelCount,  faction) 
        drawTitle(c, origin, model,   modelCount)
        drawState(c,  origin,  model,  modelCount)
        
        # Draw size, misc perks
        drawMiscInfo(c,  origin,  model,  modelCount)
        
        # Draw damage  box
        drawArmor(c,  origin,  modelCount,  model)
        
        # Draw movement box
        moveDict = {}
        moveDict[0] = { 'type': model.movePriTypeS,  'movePoints' : str(model.movePriMP),  'atkMod': "%+i" % (model.atkmod), 'defMod': "%+i" % (model.defmod) }
        if model.moveSecType is not None:
            moveDict[1] = { 'type':model.moveSecTypeS,  'movePoints' : str(model.moveSecMP),  'atkMod': "%+i" % (model.atkmod), 'defMod': "%+i" % (model.defmod) }
        drawMovement(c,  origin,  moveDict,  model,  modelCount)
        
        # Draw EW box
        ewDict = { 'detect' : model.detect,  'sensors': model.sensors, 'autocomm' : model.autocomm,  'comm': model.comm,  'ecm' : 0,  'eccm': 0 }
        for trait in model.traits_ew:            
            if trait.name.lower().startswith('ecm'):
                ewDict['ecm'] = trait.rating
            if trait.name.lower().startswith('eccm'):
                ewDict['eccm'] = trait.rating
        drawEW(c, origin, ewDict,  model,  modelCount)
        
        # Draw Ranged Weapons
        weaponsDict  = {}
        weaponL = []
        #for weapon in model.weapons_ranged:
            #print "Found weapon: %s" % weapon.name
        idx = 0
        weaponL = sorted(model.weapons_ranged,  weaponCmp)
        for weapon in weaponL:
            #print "Found weapon: %s" % weapon.name
            #print "weapon range is: %i" % weapon.rangeEX
            weaponsDict[idx] = { 
            'name': weapon.name.upper(), 
            'arc': weapon.arcS.upper(), 
            'acc' : str(weapon.acc), 
            'rangePR': str(weapon.rangePR),  
            'rangeCR': str(weapon.rangeCR), 
            'rangeER': str(weapon.rangeER), 
            'dam': str(weapon.dam),
            'special': weapon.traitsS, 
            'ammo': weapon.ammo,
            }
            idx += 1
        drawRangedWeapons(c, origin,  weaponsDict,  modelCount)
        
        # Thrown Weapons
        weaponsDict.clear()
        idx = 0
        weaponL = sorted(model.weapons_thrown,  weaponCmp)
        for weapon in weaponL:
            #print "Found weapon: %s" % weapon.name
            #print "weapon range is: %i" % weapon.rangeEX
            weaponsDict[idx] = { 
            'name': weapon.name.upper(),
            'arc': weapon.arcS.upper(),        
            'range': str(model.size), 
            'dam': str(weapon.dam),
            'special': weapon.traitsS, 
            'ammo': weapon.ammo,
            }
            idx += 1
        drawThrownWeapons(c, origin,  weaponsDict,  modelCount)
        
        # Melee Weapons
        weaponsDict.clear()
        idx = 0
        weaponL = sorted(model.weapons_melee,  weaponCmp)
        for weapon in weaponL:
            #print "Found weapon: %s" % weapon.name
            #print "weapon range is: %i" % weapon.rangeEX
            weaponDam = weapon.dam            
            if type(weapon.dam) is str:
                weaponDam = int(weaponDam[1:]) + (model.size * 2)                
                #print "Setting weapon [%s] to damage [%i]" % (weapon.name.lower(),  weaponDam)
            weaponsDict[idx] = { 
            'name': weapon.name.upper(),
            'arc': weapon.arcS.upper(),                    
            'dam': str(weaponDam),
            'special': weapon.traitsS, 
            'ammo': weapon.ammo,
            }
            idx += 1
        drawMeleeWeapons(c, origin,  weaponsDict,  modelCount)
                
        # Now generate the refernce card
        drawReferenceTraits(c,  origin,  model)
        
        drawActions(c, origin, model.actions,  modelCount)
        drawCommand(c, origin, model.actions,  modelCount)
        drawSkills(c,  origin,  modelCount)
        
        # Increment our origin
        if modelCount != 0 and modelCount % 3 == 0:
            c.showPage()
            modelCount = 0
        else:
            modelCount += 1
    # endof  for key, model in modelsDict.iteritems():   
    
    # Catch any runover models
    if modelCount != 0:
        c.showPage()

    # Save the output and exit
    c.save()
# endof drawTest

